// avlib_wrapper.h

#pragma once

#include "exec/executor.h"

#include "av_recorder/av_recorder.h"
//
[assembly : System::CLSCompliant(true)];

namespace avlib_wrapper {

	public interface class INativeConsoleCallback
	{
		[System::CLSCompliant(false)]

		console_callback_t& GetWrappedObject();
	};

	ref class I_console_callback_t ;
	class console_callback_proxy_t;


	public ref class I_console_callback_t abstract:INativeConsoleCallback{

		console_callback_proxy_t *pWrappedObject;

	public:
		I_console_callback_t();

		~I_console_callback_t();
	internal:
		[System::CLSCompliant(false)]
		virtual console_callback_t& GetWrappedObject()
			= INativeConsoleCallback::GetWrappedObject
		{
			return (console_callback_t&)*pWrappedObject;
		}

	public protected:
		virtual void on_stdout(exec_id_t id,System::IntPtr param,System::String ^ str) abstract;
		virtual void on_stderr(exec_id_t id,System::IntPtr param,System::String ^ str) abstract;
		virtual void on_exit(exec_id_t id,System::IntPtr code) abstract;
	};


	class console_callback_proxy_t:public console_callback_t{

		gcroot<I_console_callback_t^> target;
	public:
		console_callback_proxy_t(I_console_callback_t ^cb):target(cb){};
		~console_callback_proxy_t(){};
		void on_stdout_line(exec_id_t id, cparam_t param,const std::string  & str){
			target->on_stdout(id, System::IntPtr(param),gcnew System::String(str.c_str()));
		}
		void on_stderr_line(exec_id_t id, cparam_t param,const std::string  & str){
			target->on_stderr(id, System::IntPtr(param),gcnew System::String(str.c_str()));
		}
		void on_exit(exec_id_t id,int code){
			target->on_exit(id,(System::IntPtr)code);
		}
	};


	public ref class ExecutorWrapper
	{
		// TODO: Add your methods for this class here.
	private:
		Executor *pExe;

	public:
		ExecutorWrapper();
		~ExecutorWrapper();

		exec_id_t exec(System::String ^exe,System::String ^params, System::String ^workdir,I_console_callback_t ^parser,System::IntPtr data,bool support_cmd);
		bool command(exec_id_t id,System::String ^cmd);

		int pause(exec_id_t proc);
		int stop(exec_id_t proc);
		int resume(exec_id_t proc);


		bool kill(exec_id_t id);
	};


	/*

	typedef void (__stdcall* VideoDeviceCallback)(int vid,std::string devname);
	typedef void (__stdcall* AudioDeviceCallback)(int vid,std::string devname);

	typedef void (__stdcall* RecordProgressCallback)(int frame,int samplecount);
	typedef void (__stdcall* RecordErrorCallback)(int errno,std::string err_str);


	*/

	public delegate  void   VideoDeviceCallbackManaged(int vid,System::String ^devname);
	public delegate  void   AudioDeviceCallbackmanaged(int vid,System::String ^devname);

	public delegate  void   RecordProgressCallbackManaged(int frame,int nSample);
	public delegate  void   RecordErrorCallbackManaged(int error,System::String ^errtxt);
	//this will not pass to unmanaged code
	public delegate	 void	RecordFinishedCallback();

	class avlib::AVRecorder;

	public ref class AVRecorderWrapper
	{
	private:
		avlib::AVRecorder * recorder;
		int vid;
		int aid;

		static RecordProgressCallbackManaged^ onProgress;
		static RecordErrorCallbackManaged^  onError;
		static RecordFinishedCallback ^ onFinished;


		
	public:

		AVRecorderWrapper();
		~AVRecorderWrapper();

		void Init(VideoDeviceCallbackManaged^,AudioDeviceCallbackmanaged^);


		
		void use_record_device(int vid,int aid){
			this->vid = vid;
			this->aid = aid;
		}

		void set_record_callback(RecordProgressCallbackManaged^,RecordErrorCallbackManaged^,RecordFinishedCallback ^);

		void set_fps(int fps);
		bool start(System::String ^avi_tmp,System::String ^thumb_tmp,System::IntPtr hwnd);
		void set_preview_window(System::IntPtr hwnd);

		bool is_recording();
		bool stop();
		 void DoStop();

		bool query_dimension(int vid,System::Collections::ArrayList^ arr_dim);
		double get_duration();
		bool is_full_screen(){
			return false;
		}

		void set_rect(int left,int top,int width,int height);

	};
};
